#!/usr/bin/env bash

ssl_include_path() {
    case "$(uname)" in
	MINGW32*)
	    echo /mingw32/include/openssl;;
	MINGW64*)
	    echo /mingw64/include/openssl;;
	*)
	    echo "${with_openssl:-/usr}/include/openssl"
	    ;;
    esac
}

freebsd_pkg_version() {
    pkg info "$1" 2>/dev/null | sed -n 's/^Version[[:blank:]]*:[[:blank:]]*//p'
}

branch_name="$1"
shift

is_5_7_or_above="false"
is_5_8_or_above="false"
if [ "${branch_name#master}" != "${branch_name}" ]; then
  is_5_8_or_above="true"
  is_5_7_or_above="true"
elif [ "${branch_name#V5-7-}" != "${branch_name}" ]; then
  is_5_7_or_above="true"
fi

libatmver="$(for p in linux-atm-devel; do
                rpm -q --qf '%{version}\n' $p 2>/dev/null |
                  grep -v 'not installed';
              done |
              head -n1;
	      for p in libatm1-dev; do
	        dpkg-query --show -f '${Version}\n' $p 2>/dev/null;
              done | grep -v '^$';
              pacman -Q no-such-library 2>/dev/null |
                sed -n 's/^[^[:blank:]]*[[:blank:]]*//p')"
echo "libatmver=$libatmver"

libmysqlver="$(for p in libmariadb-devel; do
                rpm -q --qf '%{version}\n' $p 2>/dev/null |
                  grep -v 'not installed';
              done |
              head -n1;
	      for p in libmariadbclient-dev libmariadb-client-lgpl-dev; do
	        dpkg-query --show -f '${Version}\n' $p 2>/dev/null;
              done | grep -v '^$';
              pacman -Q mingw-w64-x86_64-libmariadbclient 2>/dev/null |
                sed -n 's/^[^[:blank:]]*[[:blank:]]*//p')"
echo "libmysqlver=$libmysqlver"

libsensorsver="$(for p in libsensors4-devel; do
                rpm -q --qf '%{version}\n' $p 2>/dev/null |
                  grep -v 'not installed';
              done |
              head -n1;
	      for p in libsensors4-dev; do
	        dpkg-query --show -f '${Version}\n' $p 2>/dev/null;
              done | grep -v '^$';
              pacman -Q no-such-package 2>/dev/null |
                sed -n 's/^[^[:blank:]]*[[:blank:]]*//p')"
echo "libsensorsver=$libsensorsver"

if ! echo "$*" | grep -Eq 'with-openssl=(no|internal)'; then
    case "$(uname -a)" in
	FreeBSD*)
	    opensslver="$(freebsd_pkg_version openssl111 2>/dev/null)"
	    if [ -z "$opensslver" ]; then
		opensslver="$(freebsd_pkg_version openssl 2>/dev/null)"
	    fi
	    if [ -z "$opensslver" ]; then
		opensslver="$(openssl version 2>&1 |
				{ read a b c; echo "$b"; })"
	    fi
	    ;;
	Linux*)
	    opensslver="$(
	    for p in openssl-devel libopenssl-devel libressl-devel; do
	      rpm -q --qf '%{version}\n' $p 2>/dev/null |
                grep -v 'not installed';
            done;
	    dpkg-query --show -f '${Version}\n' libssl-dev 2>/dev/null;
	    pacman -Q mingw-w64-x86_64-openssl 2>/dev/null |
	      sed -n 's/^[^[:blank:]]*[[:blank:]]*//p')";;
	MSYS*x86_64*)
	    opensslver="$(pacman -Q openssl-devel 2>/dev/null |
	      sed -n 's/^[^[:blank:]]*[[:blank:]]*//p')";;
	MINGW64*)
	    opensslver="$(pacman -Q mingw-w64-x86_64-openssl 2>/dev/null |
	      sed -n 's/^[^[:blank:]]*[[:blank:]]*//p')";;
	*)
	    opensslver=1.0;;
    esac
fi
echo "opensslver=$opensslver"

case "$(uname -a)" in
    FreeBSD*)
	opensshver="$(freebsd_pkg_version libssh2 2>/dev/null)";;
    Linux*)
	opensshver="$(for p in openssh-devel libssh2-devel libssh-devel; do
                rpm -q --qf '%{version}\n' $p 2>/dev/null |
                  grep -v 'not installed';
              done |
              head -n1;
              for p in libopenssh2 libssh2-1-dev libssh-dev; do
                dpkg-query --show -f '${Version}\n' $p 2>/dev/null;
              done | grep -v '^$';
              pacman -Q mingw-w64-x86_64-libssh2 2>/dev/null |
                sed -n 's/^[^[:blank:]]*[[:blank:]]*//p')"
	;;
esac
echo "opensshver=$opensshver"

case "$(uname -a)" in
    FreeBSD*)
	perldevver="$(freebsd_pkg_version perl5 2>/dev/null)";;
    Linux*)
	perldevver="$(for p in perl; do
                rpm -q --qf '%{version}\n' $p 2>/dev/null |
                  grep -v 'not installed';
              done |
              head -n1;
	      for p in libperl-dev; do
	        dpkg-query --show -f '${Version}\n' $p 2>/dev/null;
              done | grep -v '^$';
              pacman -Q mingw-w64-x86_64-perl 2>/dev/null |
                sed -n 's/^[^[:blank:]]*[[:blank:]]*//p')"
	;;
esac
echo "perldevver=$perldevver"

options=()
options+=(--enable-developer)
options+=(--enable-ipv6)
options+=("--prefix=/usr/local/net-snmp-${branch_name}")
options+=("--with-cflags=$cflags")
options+=(--with-defaults)
transports=()
# Mib names can be found as follows:
# (cd agent/mibgroup &&
# git grep -lE 'void[[:blank:]]*init_.*\(void\)|config_require\(' |
#  sed -n 's/\.h$//p')
mibs=()
case "$MODE" in
    read-only)
        ;;
    *)
        mibs+=(examples/data_set)
        mibs+=(examples/delayed_instance)
        mibs+=(examples/example)
        mibs+=(examples/notification)
        mibs+=(examples/scalar_int)
        mibs+=(examples/ucdDemoPublic)
        mibs+=(examples/watched)
        mibs+=(smux)
        ;;
esac

case "$(uname)" in
  Linux*)
      options+=(--enable-new-features)
      case "$MODE" in
          mini*|read-only)
              ;;
          *)
              $is_5_7_or_above && mibs+=(deliver/deliverByNotify)
              mibs+=(disman/event)
              #mibs+=(disman/expression) - to do: figure out why this fails on Travis
              mibs+=(disman/mteEventNotificationTable)
              mibs+=(disman/mteEventTable)
              mibs+=(disman/mteObjectsTable)
              mibs+=(disman/mteTriggerBooleanTable)
              mibs+=(disman/mteTriggerDeltaTable)
              mibs+=(disman/mteTriggerExistenceTable)
              mibs+=(disman/mteTriggerTable)
              mibs+=(disman/mteTriggerThresholdTable)
              mibs+=(disman/nslookup-mib)
              mibs+=(disman/ping-mib)
              mibs+=(disman/schedule)
              mibs+=(disman/traceroute-mib)
              mibs+=(etherlike-mib)
              mibs+=(examples/netSnmpHostsTable)
              mibs+=(hardware/cpu)
              mibs+=(hardware/fsys)
              mibs+=(hardware/memory)
              mibs+=(host)
              mibs+=(ip-forward-mib)
              mibs+=(ip-mib/inetNetToMediaTable)
              mibs+=(ip-mib/ipDefaultRouterTable)
              mibs+=(ip-mib/ipv4InterfaceTable)
              mibs+=(ip-mib/ipv6InterfaceTable)
              mibs+=(ip-mib/ipv6ScopeZoneIndexTable)
              mibs+=(mibII/ipAddr)
              mibs+=(mibII/mta_sendmail)
              mibs+=(misc/ipfwacc)
              mibs+=(sctp-mib)
              mibs+=(snmp-notification-mib)
              mibs+=(tcp-mib)
              mibs+=(testhandler)
              mibs+=(tunnel)
              mibs+=(ucd-snmp/diskio)
	      if [ -n "$libsensorsver" ]; then
		  mibs+=(hardware/sensors)
		  mibs+=(ucd-snmp/lmsensorsMib)
	      fi
              mibs+=(ucd-snmp/extensible)
              mibs+=(udp-mib)
	      mibs+=(rmon-mib)
              ;;
      esac
      # Disable MySQL support because of the following Perl test failure on
      # Travis:
      # t/1.t .. Can't load '/home/travis/build/bvanassche/net-snmp/perl/TrapReceiver/../blib/arch/auto/NetSNMP/TrapReceiver/TrapReceiver.so' for module NetSNMP::TrapReceiver: /home/travis/build/bvanassche/net-snmp/apps/.libs/libnetsnmptrapd.so.35: undefined symbol: mysql_sqlstate at /usr/lib/x86_64-linux-gnu/perl/5.22/DynaLoader.pm line 187.
      # at t/1.t line 16.
      if false && [ -n "$libmysqlver" ]; then
	  options+=(--with-mysql)
      fi
      if [ -n "$perldevver" ]; then
	  options+=(--with-perl-modules)
      else
	  options+=(--disable-embedded-perl --without-perl-modules)
      fi
      if [ -n "$libatmver" ]; then
	  transports+=(AAL5PVC)
      fi
      transports+=(IPX)
      transports+=(STD)
      $is_5_8_or_above && transports+=(UDPshared)
      if [ "$opensslver" = "" ]; then
	  options+=("--with-openssl=internal")
      else
	  if [ "$MODE" != "read-only" ]; then
	      # these MIB modules do not support read-only
	      mibs+=(snmp-usm-dh-objects-mib)
	      if [ -z "$CIRRUS_CI" ]; then
		  mibs+=(tlstm-mib)
	      fi
	      mibs+=(tsm-mib)
	  fi
      fi
      options+=("--with-default-snmp-version=2")
      options+=("--with-systemd")
      # Disabled modules because troublesome: Rmon ipfwchains/ipfwchains ucd-snmp/lmSensors
    ;;
  darwin*|Darwin*)
      case "$MODE" in
          mini*|read-only)
              ;;
          *)
              mibs+=(disman/nslookup-mib)
              mibs+=(host)
              mibs+=(if-mib)
              mibs+=(mibII/mta_sendmail)
              mibs+=(misc/ipfwacc)
              mibs+=(snmp-notification-mib)
              mibs+=(snmp-usm-dh-objects-mib)
              mibs+=(tcp-mib)
              mibs+=(ucd-snmp/diskio)
              mibs+=(ucd-snmp/extensible)
              mibs+=(udp-mib)
              mibs+=(Rmon)
              ;;
      esac
      if [ "${TRAVIS_OS_NAME}" == "osx" ]; then
          options+=("--with-openssl=$(brew --prefix openssl)")
          # On Travis OS/X linking the Perl modules fails with "undefined symbol
          # _BN_bin2bn" etc.
          options+=(--disable-embedded-perl --without-perl-modules)
      fi
    ;;
  FreeBSD*)
      case "$MODE" in
          mini*|read-only)
              ;;
          *)
              mibs+=(disman/nslookup-mib)
              mibs+=(host)
              mibs+=(if-mib)
              mibs+=(mibII/mta_sendmail)
              mibs+=(misc/ipfwacc)
              mibs+=(sctp-mib)
              mibs+=(snmp-notification-mib)
              mibs+=(snmp-usm-dh-objects-mib)
              mibs+=(tcp-mib)
              mibs+=(ucd-snmp/diskio)
              mibs+=(ucd-snmp/extensible)
              mibs+=(udp-mib)
              mibs+=(Rmon)
              ;;
      esac
      options+=(--disable-embedded-perl --without-perl-modules)
    ;;
  CYGWIN*)
      export ENV_SEPARATOR=":"
      mibs+=(ucd-snmp/extensible)
      mibs+=(winExtDLL)
      options+=(--disable-embedded-perl --without-perl-modules)
    ;;
  MINGW*)
      options+=(--disable-embedded-perl)
      mibs+=(host)
      mibs+=(snmp-notification-mib)
      mibs+=(ucd-snmp/dlmod)
      mibs+=(ucd-snmp/extensible)
      mibs+=(winExtDLL)
      options+=(--without-perl-modules)
    ;;
  MSYS*)
      options+=(--disable-embedded-perl)
      mibs+=(host)
      mibs+=(snmp-notification-mib)
      mibs+=(ucd-snmp/dlmod)
      mibs+=(ucd-snmp/extensible)
      mibs+=(winExtDLL)
      options+=(--without-perl-modules)
      # The config.guess script in the Net-SNMP source tree is too old to
      # recognize the MSYS2 environment. Hence the explicit --build=... option.
      # See also
      # http://git.savannah.gnu.org/cgit/automake.git/tree/lib/config.guess.
      options+=("--build=x86_64-pc-mingw32")
    ;;
  *)
    echo "Unknown OS $(uname)."
    ;;
esac

with_openssl=""
for o in "${options[@]}"; do
    if [ "${o#--with-openssl=}" != "$o" ]; then
        with_openssl="${o#--with-openssl=}"
    fi
done
if [ "$opensslver" != "" ] &&
	grep -rqw BIO_dgram_get_peer "$(ssl_include_path)" 2>/dev/null
then
    transports+=(DTLSUDP TLSTCP)
fi
if [ "$with_openssl" != "internal" ] && $is_5_8_or_above &&
       [ -e "$(ssl_include_path)/aes.h" ] &&
       [ -e "$(ssl_include_path)/evp.h" ]; then
       options+=(--enable-blumenthal-aes)
fi
security_modules=(usm tsm)
if [ -e /usr/include/krb5.h ]; then
    security_modules+=(ksm)
fi
case "$(uname)" in
    MSYS*|MINGW*)
	# Do not enable Python support on MinGW32 nor for the MSYS build
	# environment because the Python interpreter has been built on these
	# environments with Visual C++. That compiler is incompatible with gcc.
        ;;
    *)
	# Do not enable Python support for Cirrus CI because on Cirrus linking
	# with Python fails as follows (this is probably a bug in Net-SNMP):
	# /usr/bin/ld: /tmp/cirrus-ci-build/snmplib/.libs/libnetsnmp.a(snmp_client.o): relocation R_X86_64_32S against `a local symbol' can not be used when making a shared object; recompile with -fPIC
	if python3 -c 'import setuptools' 1>/dev/null 2>&1 &&
	       [ -z "$CIRRUS_CI" ]; then
	    options+=(--with-python-modules)
	fi
    esac

case "$MODE" in
    disable-set)
        options+=(--disable-set-support);;
    mini)
        options+=(--enable-mini-agent);;
    minimalist)
        options+=(--enable-minimalist);;
    read-only)
        options+=(--enable-read-only);;
    regular|"")
        ;;
    *)
        echo "Error: unknown build type $MODE"
        exit 1;;
esac

[ "${opensshver#2}" != "${opensshver}" ] && transports+=(SSH)
set -x
./configure "${options[@]}" --with-transports="${transports[*]}" \
            --with-security-modules="${security_modules[*]}"	 \
	    --with-mib-modules="${mibs[*]}" "$@"
